import { replaceAllArrow, toArray, escapeRegExp, isLight } from './helpers'

/**
 * 生成正则规则
 * @author zhengchj
 * @param highlighter  高亮关键词对象
 * @returns {*}        返回正则规则
 * @private
 */
const _createRule = highlighter => {
  let { word } = highlighter
  //替换高亮词中的<,>
  word = replaceAllArrow(word)
  //正则特殊字符转义
  word = escapeRegExp(word)
  // 拆解高亮关键词
  word = _spreadWord(word)
  return word
}

/**
 * 展开高亮关键词，每个字符前后加正则规则
 * @example 手机 -> (<span class="hl[^"]*"[^<>]+>手</span>|手)(<span class="hl[^"]*"[^<>]+>机</span>|机)
 * @param word   高亮关键词
 * @returns string
 */
const _spreadWord = word => {
  const chars = word.match(/(&lt;|&gt;|\\[\\^$.*+?()[\]{}|]|.)/gi)
  let newWord = ''
  for (const char of chars) {
    newWord += _buildCharRegExp(char)
  }
  return newWord
}
/**
 * 为字符构建正则表达式
 * @param char
 * @returns string
 */
const _buildCharRegExp = char => `((<span class="hl[^"]*"[^<>]+>)+${char}(</span>)+|${char})`
/**
 *
 * 原则：后端传的文本如果含有左右尖括号，需要后端转义，标签的左右尖括号不用转义
 *
 * 执行高亮操作
 * @author zhengchj
 * @param targetStr     目标字符串
 * @param highlighters  高亮关键词集合或对象
 * @return string       执行高亮后的字符串
 */
export const highlight = (targetStr, highlighters) => {
  if (!targetStr) {
    return ''
  }
  let str = targetStr
  toArray(highlighters).forEach(item => {
    let { word, color } = item
    if (!word) {
      return
    }
    let rule = _createRule(item)
    //高亮关键词匹配规则,标签中的内容不可匹配
    const regExp = new RegExp(`((${rule})(?![^<>]*>))`, 'gi')
    //判断是否浅色
    const fontColor = isLight(color) ? '#000' : '#fff'
    //高亮关键词加高亮标签
    str = str.replace(regExp, word => {
      let i = 1
      return word.replace(/((&lt;|&gt;|[^<>])(?![^<>]*>))/gi, w => {
        let result = ''
        if (i === 1) {
          result = `<span class="hl hl-start" style="background-color: ${color};color: ${fontColor};">${w}</span>`
        } else {
          result = `<span class="hl" style="background-color: ${color};color: ${fontColor};">${w}</span>`
        }
        i++
        return result
      })
    })
  })
  return str
}
